#ifndef INTER_CODE_H
#define INTER_CODE_H
#include "symbol.h"


#define INVALID_LB_NAME            "@null"
#define GEN_NAME_LB_PREFIX          "@L"
#define GEN_NAME_TMP_VAR_PREFIX     ".t"
typedef enum operator
{
	IR_OP_DECL, 
	// 函数入口和出口,因为在汇编语言层面，入口和出口都有操作
	IR_OP_FUN_ENTRY,
	IR_OP_FUN_EXIT,
	IR_OP_ASSIGN, //赋值运算
	//算数运算
	IR_OP_ADD,
	IR_OP_SUB,
	IR_OP_MUL,
	IR_OP_DIV,
	IR_OP_MOD, 
	IR_OP_NEG, // 取负 eg: NEG result,arg1 => result = -arg1
	//比较运算
	IR_OP_GT, // eg: GT result,arg1,arg2 => result=arg1 > arg2
	IR_OP_GE,
	IR_OP_LT, 
	IR_OP_LE,
	IR_OP_EQU, // 判等
	IR_OP_NEQU, 
	//逻辑运算
	IR_OP_NOT, // 逻辑非 eg: NOT result,arg1 => result=!arg1
	IR_OP_AND,
	IR_OP_OR, 
	
	//指针运算
	IR_OP_LEA,//取址 这也是x86汇编指令
	IR_OP_STORE, //        eg: STORE result, arg1 => *arg1 = result   //  STR Rd, [Rn]​; 将 result 的值存储到内存地址 arg1
	IR_OP_LOAD, //         eg: LOAD  result, arg1 => result = *arg1   //  LDR Rd, [Rn];​ 从内存地址 arg1 加载数据到 result
	//跳转
	IR_OP_JMP, // 无条件跳转 eg: JMP result => goto result
	IR_OP_JF,     // 为假则跳转	 eg: JF result,arg1 => if(!arg1) goto result  
	IR_OP_JT,    // 为真则跳转	 eg: JT result,arg1 => if(arg1)  goto result
	IR_OP_JE,    // 相等则跳转
	IR_OP_JNE,  // 不相等则跳转
	//函数调用
	IR_OP_ARG, // 参数传递 eg: ARG arg1 => 传递参数arg1
	IR_OP_PROC, // 调用过程 eg: PROC fun => 调用fun函数,fun()
	IR_OP_CALL, // 调用函数 eg: CALL result,fun => 调用fun函数,返回值result=fun()
	IR_OP_RET,      //直接返回 eg: RET => return
	IR_OP_RET_VAL,  //带数据返回 eg:RET arg1 => return arg1
}operator_e;

typedef struct inter_inst
{
	char label[GEN_NAME_MAX_LEN];  // 标签
	operator_e op;  // 操作符
	var_t *result; // 运算结果
	struct inter_inst *jmp_target; // 跳转标号
	var_t *arg1; // 参数1
	var_t *arg2; // 参数2
	fun_t *fun;  // 函数,个别情况才使用

	struct list_head entry; // 用于加入链表
	int inst_id; // 指令的序号，为了调试
	//	struct list_head label_entry;
	/* TODO */
	//...
}inter_inst_t;

inter_inst_t *new_general_inst(operator_e op, var_t *result, 
                                 var_t *arg1, var_t *arg2);
inter_inst_t *new_fun_inst(operator_e op, fun_t *fun, var_t *result);
inter_inst_t *new_push_arg_inst(var_t *arg); 
inter_inst_t *new_label_inst(const char *user_lb);
inter_inst_t *new_jump_inst(operator_e op, inter_inst_t *target, 
                                 var_t *arg1, var_t *arg2);                            
void print_inter_code(struct list_head *head);
//inter_inst_t *new_invalid_label(void);
//bool is_invalid_label(inter_inst_t *inst);
#endif